Skip to content

Conversation

@msirringhaus
Copy link
Collaborator

Note: This is based on the translations-PR to utilize translatable strings here, too. So for now, only look at the last commit.

Points of contention:

  1. Failing to determine the application name is currently considered a non-fatal error, and will only be displayed with an "unknown application"-placeholder in the UI
  2. /proc/PID/comm is used for the application name, instead of the full absolute path to the binary. I think the full path may confuse more than help novice users, but I'm open to change that.
  3. Only rp_id is used, w/o cross-referencing "origin".
  4. I squished the new context into the title, which probably isn't great for translations or UX. more_context We could think about adding two new fields in the UI below the title that could simply read
    Requesting party/server/URL/?: webauthn.io
    Requesting application: firefox
    
    Or have one or two additional full sentences instead of this "table of context". I'm open to suggestions.
    If we stay with the current proposal, I would need to add more translations-metadata to make it clear to potential translators how the new strings are used.

@AlfioEmanueleFresta
Copy link
Member

As discussed in the past, totally agree on adding the caller identity.

I appreciate this is a reference implementation, but IMO there's value in bringing our recommendations/best practices on wording, hence sharing a bit more feedback:

  • I believe we should adopt 'passkeys', aligning with other platforms/clients. This aligns with Include the passkey icon in the CDA QR code #99 (using the passkey logo).
    • I don't have a strong opinion as to whether we should do this: (a) for all credentials, to keep it simple; or (b) for FIDO2 credentials only; or (c) for FIDO2 discoverable credentials only (technically correct as per official definition?).
    • Quick check - Android appear to do either (a) or (b), as they don't support FIDO U2F creation but still show 'passkey' when downgrading to a connected U2F authenticator.
  • I think "Create a credential [...] via firefox" may be confusing to users, as it would suggest the application is mediating the passkey creation. E.g. in the case of "via Google Chrome" users may suspect the credential will be stored in Chrome. I would prefer a more verbose, but possibly clearer version.
    • Windows Hello says something like: This request comes from the app "firefox.exe" from "Mozilla Corporation".
    • Apple (which has signed apps) uses similar text but just the verified app name: "Google Chrome" is trying to verify your identity on "google.com".
  • The main threat here IMO is spoofing an application name. Does adding the PID here provide any extra assurance? Ie. any security-conscious users who want to do checks on their own.

How about something like:

Create a passkey for webauthn.io

"firefox" (process ID: 1234) is asking to create a credential to sign in to "webauthn.io".
Only proceed if you trust this process.

And:

Use a passkey for webauthn.io

"firefox" (process ID: 1234) is asking to use your credential to sign in to "webauthn.io".
Only proceed if you trust this process.

Figmas for other platforms from passkeycentral.org.

@msirringhaus, @iinuwa, WDYT?

@timcappalli I don't know of any published guidelines for platforms, but would be curious to hear your thoughts if you have any, or if you know someone who might.

@msirringhaus
Copy link
Collaborator Author

I added more context now. We can debate if we need PID, binary path and application name, but I have put everything in there now, to see how it looks. I also tried to make the UI a bit cleaner by adding some spacing and separators. Still far from a polished UI, but better than nothing.
Also added ability to add context for translators and used it already.
image

@msirringhaus msirringhaus force-pushed the ui_more_request_context branch from 9945cd6 to dec5b0f Compare October 30, 2025 14:12
…lly up to a given limit instead of giving them a big minimal height
@timcappalli
Copy link

@AlfioEmanueleFresta I think your proposed UI/text makes sense and nicely aligns with other experiences in the ecosystem, while also addressing unique considerations for Linux (showing process ID in addition to name).

Copy link
Member

@iinuwa iinuwa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a draft about this a couple weeks ago but I've lost it. I'll try to recover it.

I think this is fine as is (besides the changes mentioned below). Because of namespaces, all of the information shown can be spoofed by an attacker, but it's the best we can do for now. We can revisit in the future.

After migrating to use PIDFDs instead, we can merge this. Any more UI polish can happen later.

Thank you!

Comment on lines 55 to 107
let sender_unique_name = header.sender()?;

tracing::debug!("Received request from sender: {}", sender_unique_name);

// 2. Use the connection to query the D-Bus daemon for more info
let proxy = match zbus::Proxy::new(
connection,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
)
.await
{
Ok(p) => p,
Err(e) => {
tracing::error!("Failed to establish DBus proxy to query peer info: {e:?}");
return None;
}
};

// 3. Get the Process ID (PID) of the peer
let pid_result = match proxy
.call_method("GetConnectionUnixProcessID", &(sender_unique_name))
.await
{
Ok(pid) => pid,
Err(e) => {
tracing::error!("Failed to get peer PID via DBus: {e:?}");
return None;
}
};
let pid: u32 = match pid_result.body().deserialize() {
Ok(pid) => pid,
Err(e) => {
tracing::error!("Retrieved peer PID is not an integer: {e:?}");
return None;
}
};

// 4. Get binary path via PID from /proc file-system
// TODO: To be REALLY sure, we may want to look at /proc/PID/exe instead. It is a symlink to
// the actual binary, giving a full path instead of only the command name.
// This should in theory be "more secure", but also may disconcert novice users with no
// technical background.
let command_name = match std::fs::read_to_string(format!("/proc/{pid}/comm")) {
Ok(c) => c.trim().to_string(),
Err(e) => {
tracing::error!(
"Failed to read /proc/{pid}/comm, so we don't know the command name of peer: {e:?}"
);
return None;
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use connection.peer_credentials.process_fd() here instead? Using a pidfd is safer against certain kinds of attacks.

Something like this (with proper error handling) should work to parse the PID from that pidfd:

let pidfd = connection.peer_credentials.process_fd()
    .expect("pidfd to be retrieved from DBus connection")
    .into_raw_fd();
let fdinfo_str = std::fs::read_to_string(format!("/proc/self/fdinfo/{pidfd}"))
    .map_err(|err| format!("Failed to read fdinfo from procfs: {err}"))?;

let pid_from_pidfd: pid_t = fdinfo_str
    .split("\n")
    .map(|line| line.split_once(":\t").expect("fdinfo text to be returned"))
    .find(|(k, _)| *k == "Pid")
    .expect("Pid field to exist in fdinfo")
    .1
    .parse()
    .expect("valid PID from fdinfo");

I think there's also a recently added PIDFD_INFO_PID ioctl to make this shorter, but I don't know when that was added to the kernel or if it was backported. This should be compatible back to 5.3.

@iinuwa iinuwa merged commit ae00a6f into linux-credentials:main Nov 28, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants